package scaladuct

import java.lang.Class

/**
 * <p>
 * Created by IntelliJ IDEA.
 * User: zslajchrt
 * Date: Oct 19, 2010
 * Time: 2:32:47 PM
 */

object ConfigPageDecorator {
}

@SerialVersionUID(1L)
class ConfigPageDecorator[X](val decoratedPage: ConfigPage[X]) extends ConfigPage[X] {
  def id = decoratedPage.id

  def consume(cookie: Cookie): ConfigResult[InstanceType] = decoratedPage.consume(cookie)

  def getCookie() = decoratedPage.getCookie

  type Cookie = decoratedPage.Cookie

  override def unconsume(result: ConfigResult[X]) = decoratedPage.unconsume(result)

  override def canUnconsume(result: ConfigResult[X]): Boolean = decoratedPage.canUnconsume(result)

  override def cancel() = decoratedPage.cancel

  override def extension[T](extClass: Class[T]) = {
    super.extension(extClass) match {
      case None => decoratedPage.extension(extClass)
      case Some(ext) => Some(ext)
    }
  }

  override def hashCode = decoratedPage.hashCode

  override def canEqual(other: Any) = decoratedPage.canEqual(other)

  override def equals(obj: Any) = decoratedPage.equals(obj)
}

class PreDecoratedPage[H, T](val headPage: ConfigPage[H],
                             val tailPage: ConfigPage[T],
                             val decorationCallback: (Starter[H]) => Unit) extends {
val id = headPage.id
} with ConfigPage[T] {
  def this(headPage: ConfigPage[H], tailPage: ConfigPage[T]) = this (headPage, tailPage, (_) => {})

  type Cookie = headPage.Cookie

  def getCookie() = headPage.getCookie

  def consume(cookie: Cookie): ConfigResult[T] = {
    headPage.consume(cookie) match {
      case NextPage(nextPage) => {
        NextPage(new PreDecoratedPage(nextPage, tailPage, decorationCallback))
      }
      case NewStarter(headStarter) => {
        decorationCallback(headStarter)
        NextPage(tailPage)
      }
    }
  }

  override def cancel() = headPage.cancel
}

class PostDecoratedPage[H, T](val headPage: ConfigPage[H],
                              val tailPage: ConfigPage[T],
                              val decorationCallback: (Starter[T]) => Unit) extends {
val id = headPage.id
} with ConfigPage[H] {
  def this(headPage: ConfigPage[H], tailPage: ConfigPage[T]) = this (headPage, tailPage, (_) => {})

  type Cookie = headPage.Cookie

  def getCookie() = headPage.getCookie

  def consume(cookie: Cookie): ConfigResult[H] = {
    headPage.consume(cookie) match {
      case NextPage(nextPage) => {
        NextPage(new PostDecoratedPage(nextPage, tailPage, decorationCallback))
      }
      case NewStarter(headStarter) => {
        NextPage(new TailPageWrapper(headStarter, tailPage))
      }
    }
  }

  override def cancel() = headPage.cancel

  class TailPageWrapper(val starter: Starter[H], val tailPage: ConfigPage[T]) extends {
  val id = tailPage.id
  } with ConfigPage[H] {
    type Cookie = tailPage.Cookie

    def getCookie() = tailPage.getCookie

    def consume(cookie: Cookie): ConfigResult[H] = {
      tailPage.consume(cookie) match {
        case NextPage(nextPage) => {
          NextPage(new TailPageWrapper(starter, nextPage))
        }
        case NewStarter(tailStarter) => {
          decorationCallback(tailStarter)
          NewStarter(starter)
        }
      }
    }

    override def cancel() = tailPage.cancel
  }

}

